import locale

import cocos, pyglet
from cocos.actions import *
from cocos.scenes import *
from cocos.director import director

import backgrounds, models, message, city_display, gui, map_editor, cutscenes, menu, hordes, sound
from config import current as conf

class MapLayer(cocos.layer.Layer):
    """Displays the underlying map"""
    def __init__(self, state):
        super(MapLayer, self).__init__()
        self.state = state
        self.add(backgrounds.ImageLayer(state.bg_filename))

class GUILayer(cocos.layer.Layer):
    """Displays global GUI elements"""
    def __init__(self, state):
        super(GUILayer, self).__init__()
        self.state = state
        self.add(gui.ClickableLabel("[Next]", self.next_turn, (720, 600-30)), z = 1)
        self.status_label = cocos.text.Label("",
            font_name=conf.title_font, font_size=20,
            color=(255,255,255,255), x=400, y=600,
            anchor_x='center', anchor_y='top')
        self.add(self.status_label, z=1)
        self.bg = cocos.layer.ColorLayer(0,0,0,200)
        self.bg.position = (0, 282)
        self.add(self.bg, z = 0)

        self.update()

    def next_turn(self):
        self.state.advance()
        self.update()
        
    def update(self):
        total_population = locale.format_string("%d Survivors",
            sum(city.population for city in self.state.cities if city.status == models.City.CLEAN), True)
        year = self.state.current_year
        research = self.state.research * 100
        self.status_label.element.text = "%s AD -- %s -- %.0f%% done with cure"%(year, total_population, research)

class MovementGUILayer(cocos.layer.Layer):
    """Displays movement GUI elements"""
    def __init__(self, city):
        super(MovementGUILayer, self).__init__()

class GameScene(cocos.scene.Scene):
    """Container for various display/control layers"""
    def __init__(self, state):
        """Construct a game scene from a given initial GameState"""
        super(GameScene, self).__init__()
        self.state = state
        self.gamegrid = GameGrid(state)

        # add the map and cities
        self.add(MapLayer(state), z = 0)
        for city in state.cities:
            self.add(city_display.CityLayer(city, self.gamegrid), z = 2)
        
        self.add(hordes.HordesLayer(state, self.gamegrid), z =1)
        
        # add the status bar
        self.messages = message.MessagesLayer()
        self.add(self.messages, z = 12)

        self.add(GUILayer(state), z = 3)
        self.add(map_editor.MapEditorLayer(state, self.gamegrid), z = 10)
        self.add(menu.InGameMenuLayer(self.state), z = 11)
        
        # show some intro messages using the status bar
        self.do(Delay(1) + self.messages.show_action("Welcome to Necropoli!"))

        # handle ending conditions
        state.handle("win", lambda:director.replace(
            FadeTransition(cutscenes.Win(), conf.long_transition_time)))
        state.handle("loss", lambda:director.replace(
            FadeTransition(cutscenes.Loss(), conf.long_transition_time)))

    def on_enter(self):
        sound.start_game()
        super(GameScene, self).on_enter()

class GameGrid(object):
    def __init__(self, state):
        super(GameGrid, self).__init__()
        self.w = director.window.width
        self.h = director.window.height
        self.gw, self.gh = state.dimensions

    def cell_to_pixel(self, grid_pos):
        return ((grid_pos[0] + 0.5 )*(self.w/self.gw),
                (grid_pos[1] + 0.5 )*(self.h/self.gh))

    def pixel_to_cell(self, pixel_pos):
        return (int(pixel_pos[0]/float(self.w/self.gw)),
                int(pixel_pos[1]/float(self.h/self.gh)))